package com.lemon.soft.bookingroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lemon.soft.bookingroom.dao.MeetingRoomsDao;
import com.lemon.soft.bookingroom.dto.BookingCreateDTO;
import com.lemon.soft.bookingroom.dto.BookingQueryDTO;
import com.lemon.soft.bookingroom.entity.MeetingRoomsEntity;
import com.lemon.soft.bookingroom.entity.RoomTimeStatusEntity;
import com.lemon.soft.bookingroom.entity.UsersEntity;
import com.lemon.soft.bookingroom.service.*;
import com.lemon.soft.bookingroom.util.PageUtils;
import com.lemon.soft.bookingroom.util.Query;
import com.lemon.soft.bookingroom.vo.BookingVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.lemon.soft.bookingroom.dao.BookingsDao;
import com.lemon.soft.bookingroom.entity.BookingsEntity;
import org.springframework.transaction.annotation.Transactional;


@Service("bookingsService")
public class BookingsServiceImpl extends ServiceImpl<BookingsDao, BookingsEntity> implements BookingsService {
    @Autowired
    private MeetingRoomsService meetingRoomsService;
    @Autowired
    private MeetingRoomsDao meetingRoomsDao;
    @Autowired
    private RoomTimeStatusService roomTimeStatusService;

    @Autowired
    private RefundRulesService refundRuleService;

    @Autowired
    private CancellationRecordsService cancellationRecordService;

    @Autowired
    private UsersService userService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<BookingsEntity> page = this.page(
                new Query<BookingsEntity>().getPage(params),
                new QueryWrapper<BookingsEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<MeetingRoomsEntity> queryAvailableRooms(BookingQueryDTO queryDTO) {
        // 1. 解析查询条件
        LocalDateTime startTime = queryDTO.getStartTime();
        LocalDateTime endTime = queryDTO.getEndTime();
        Integer participantCount = queryDTO.getParticipantCount();
        List<String> reqqequipment = queryDTO.getRequiredEquipment();

        // 2. 查询符合条件的会议室
        LambdaQueryWrapper <MeetingRoomsEntity> roomQuery = new LambdaQueryWrapper<>();
        roomQuery.ge(MeetingRoomsEntity::getSeatCount, participantCount);
        List<MeetingRoomsEntity> candidateRooms = meetingRoomsDao.selectList(roomQuery);
        System.out.println(candidateRooms);
        for (String s:reqqequipment)
        {
            candidateRooms = candidateRooms.stream().filter(room -> room.getEquipment().contains(s)).collect(Collectors.toList());
        }



        // 3. 过滤出时间段空闲的会议室
        List<MeetingRoomsEntity> availableRooms = new ArrayList<>();
        for (MeetingRoomsEntity room : candidateRooms) {
            // 查询该会议室在指定时间段内的状态
            QueryWrapper<RoomTimeStatusEntity> statusQuery = new QueryWrapper<>();
            statusQuery.eq("room_id", room.getRoomId())
                    .and(wrapper ->
                            wrapper.between("start_time", startTime, endTime)
                                    .or()
                                    .between("end_time", startTime, endTime)
                                    .or()
                                    .lt("start_time", startTime)
                                    .and(wrapper2 -> wrapper2.gt("end_time", endTime))
                    )
                    .eq("is_delete", 0);
            List<RoomTimeStatusEntity> statusList = roomTimeStatusService.list(statusQuery);

            // 如果没有冲突的预订，则会议室可用
            if (statusList.isEmpty() || statusList.stream()
                    .allMatch(status -> "空闲".equals(status.getStatus()) || "维护".equals(status.getStatus()))) {
                availableRooms.add(room);
            }
        }

        return availableRooms;
    }
    @Transactional
    @Override
    public String processPayment(Integer bookingId) {
        // 1. 查询订单
        BookingsEntity booking = this.getById(bookingId);
        if (booking == null || booking.getIsDelete() == 1) {
            //TODO
            //throw new BusinessException("订单不存在");
            return "订单不存在";
        }

        // 2. 检查订单是否已过期
        if (booking.getPaymentStatus() == 2) {
            //TODO
            //throw new BusinessException("订单已取消");
            return "订单已取消";
        }

        // 检查订单是否超时
        LocalDateTime expireTime = booking.getCreateTime().plusMinutes(30);
        if (LocalDateTime.now().isAfter(expireTime)) {
            // 订单已过期，释放会议室
            releaseRoom(bookingId);
            //TODO
            //throw new BusinessException("订单已过期，无法支付");
            return "订单已过期，无法支付";
        }

        // 3. 更新支付状态
        booking.setPaymentStatus(1);
        booking.setPaymentTime(LocalDateTime.now());
        booking.setUpdateTime(LocalDateTime.now());
        this.updateById(booking);

        // 4. 更新会议室状态为"预定"
        QueryWrapper<RoomTimeStatusEntity> statusQuery = new QueryWrapper<>();
        statusQuery.eq("booking_id", bookingId)
                .eq("is_delete", 0);
        RoomTimeStatusEntity roomTimeStatus = roomTimeStatusService.getOne(statusQuery);

        if (roomTimeStatus != null) {
            roomTimeStatus.setStatus("预定");
            roomTimeStatus.setUpdateTime(LocalDateTime.now());
            roomTimeStatusService.updateById(roomTimeStatus);
        }

        return "支付成功";
    }
    @Transactional
    @Override
    public Map<String, Object> createBooking(BookingCreateDTO createDTO, Integer userId) {
        // 1. 检查用户是否存在
        UsersEntity user = userService.getById(userId);
        if (user == null || user.getIsDelete() == 1) {
//            throw new BusinessException("用户不存在");
            Map<String, Object> map = new HashMap<>();
            map.put( "message", "用户不存在");
            return map;
        }

        // 2. 检查会议室是否存在且可用
        MeetingRoomsEntity meetingRoom = meetingRoomsService.getById(createDTO.getRoomId());
        if (meetingRoom == null || meetingRoom.getIsDelete() == 1) {
//            throw new BusinessException("会议室不存在");
            Map<String, Object> map = new HashMap<>();
            map.put( "message", "会议室不存在");
            return map;
        }

        // 3. 检查时间段是否可用
        QueryWrapper<RoomTimeStatusEntity> statusQuery = new QueryWrapper<>();
        statusQuery.eq("room_id", createDTO.getRoomId())
                .and(wrapper ->
                        wrapper.between("start_time", createDTO.getStartTime(), createDTO.getEndTime())
                                .or()
                                .between("end_time", createDTO.getStartTime(), createDTO.getEndTime())
                                .or()
                                .lt("start_time", createDTO.getStartTime())
                                .and(wrapper2 -> wrapper2.gt("end_time", createDTO.getEndTime()))
                )
                .eq("is_delete", 0)
                .ne("status", "空闲");
        List<RoomTimeStatusEntity> statusList = roomTimeStatusService.list(statusQuery);

        if (!statusList.isEmpty()) {
            Map<String, Object> map = new HashMap<>();
            map.put( "message", "该时间段会议室已被预订");
            return map;
//            throw new BusinessException("该时间段会议室已被预订");
        }

        // 4. 计算总价格
        long hours = ChronoUnit.HOURS.between(createDTO.getStartTime(), createDTO.getEndTime());

        BigDecimal totalPrice = meetingRoom.getPrice().multiply(new BigDecimal(hours));


        // 5. 创建预订订单
        BookingsEntity booking = new BookingsEntity();
        booking.setUserId(userId);
        booking.setRoomId(createDTO.getRoomId());
        booking.setStartTime(createDTO.getStartTime());
        booking.setEndTime(createDTO.getEndTime());

        booking.setTotalPrice(totalPrice);
        booking.setPaymentStatus(0); // 未支付
        booking.setCreateTime(LocalDateTime.now());
        booking.setUpdateTime(LocalDateTime.now());
        booking.setIsDelete(0);

        this.save(booking);

        // 6. 锁定会议室时间段
        RoomTimeStatusEntity roomTimeStatus = new RoomTimeStatusEntity();
        roomTimeStatus.setRoomId(createDTO.getRoomId());
        roomTimeStatus.setStartTime(createDTO.getStartTime());
        roomTimeStatus.setEndTime(createDTO.getEndTime());
        roomTimeStatus.setStatus("锁定"); // 锁定状态
        roomTimeStatus.setBookingId(booking.getBookingId());
        roomTimeStatus.setCreateTime(LocalDateTime.now());
        roomTimeStatus.setUpdateTime(LocalDateTime.now());
        roomTimeStatus.setIsDelete(0);

        roomTimeStatusService.save(roomTimeStatus);
        booking.setStatusId(roomTimeStatus.getStatusId());
        this.updateById(booking);

        // 7. 返回订单信息
        Map<String, Object> result = new HashMap<>();
        result.put("bookingId", booking.getBookingId());
        result.put("totalPrice", totalPrice);
        result.put("expireTime",booking.getCreateTime().plusMinutes(30) ); // 30分钟后过期
        return result;
    }
/**
 * 查询客户的订单信息
 */
    @Override
    public List<BookingVo> selectByUserId(Integer userId) {
        LambdaQueryWrapper<BookingsEntity> bookingsEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bookingsEntityLambdaQueryWrapper.eq(BookingsEntity::getUserId,userId);

        List<BookingVo> collect = this.list(bookingsEntityLambdaQueryWrapper).stream().map(booking -> {
            BookingVo bookingVo = new BookingVo();
            BeanUtils.copyProperties(booking, bookingVo);
            bookingVo.setRoomName(meetingRoomsService.getById(booking.getRoomId()).getRoomName());
            return bookingVo;
        }).collect(Collectors.toList());

        return collect;
    }


    @Transactional
    @Override
    public void checkBookingTimeout() {
        // 查询所有未支付且创建时间超过30分钟的订单
        LocalDateTime thirtyMinutesAgo = LocalDateTime.now().minusMinutes(30);
        QueryWrapper<BookingsEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_status", 0)
                .lt("create_time", thirtyMinutesAgo)
                .eq("is_delete", 0);
        List<BookingsEntity> timeoutBookings = this.list(queryWrapper);

        // 处理超时订单
        for (BookingsEntity booking : timeoutBookings) {
            releaseRoom(booking.getBookingId());
        }
    }
    /**
     * 释放被锁定的会议室
     */
    private void releaseRoom(Integer bookingId) {
        // 更新订单状态为已取消
        BookingsEntity booking = this.getById(bookingId);
        if (booking != null) {
            booking.setPaymentStatus(2);
            booking.setUpdateTime(LocalDateTime.now());
            this.updateById(booking);
        }

        // 更新会议室状态为空闲
        QueryWrapper<RoomTimeStatusEntity> statusQuery = new QueryWrapper<>();
        statusQuery.eq("booking_id", bookingId)
                .eq("is_delete", 0);
        RoomTimeStatusEntity roomTimeStatus = roomTimeStatusService.getOne(statusQuery);

        if (roomTimeStatus != null) {
            roomTimeStatus.setStatus("空闲");
            roomTimeStatus.setBookingId(null);
            roomTimeStatus.setUpdateTime(LocalDateTime.now());
            roomTimeStatusService.updateById(roomTimeStatus);
        }
    }
}